---
title: Endpoints
summary: Endpoint catalog for PdfAPI, with per-controller detail pages.
status: draft
owner: Not determined from source
last_reviewed: 2026-09-17
library: PdfAPI
reference_type: embedded
---

# Endpoints

PdfAPI exposes 13 endpoints across six controllers: document conversion, merge, and page extraction; tracking status and download; PDF inspection and validation; and a build-version endpoint. All 13 endpoints are attribute-routed; a convention route is registered but matched by no live action.

This page is the endpoint catalog and hub. Each controller's endpoints are documented in detail on its own page under `endpoints/`.

## Route composition

| Aspect | Finding |
| --- | --- |
| Routing mode | Both are registered — `config.MapHttpAttributeRoutes()` and the convention route `api/{controller}/{id}` (`DefaultApi`) — but every live action carries `[Route]`, so only attribute routing resolves any action* |
| Convention template | `api/{controller}/{id}` — registered, matched by no live action* |
| Versioning | `[RoutePrefix("v1")]` / `[RoutePrefix("v1/info")]` / `[RoutePrefix("v1/legacy")]` on 11 of 13 endpoints; `ApiInfoController` carries no `[RoutePrefix]` |
| Base path | Application base URL (host + virtual directory) prefixed to every route below |

A fully resolved route composes the controller's `[RoutePrefix]` with the action's `[Route]` fragment — for example `[RoutePrefix("v1")]` + `[Route("convert")]` → `v1/convert`.
`ApiInfoController` carries no `[RoutePrefix]`, so its route (`buildVersion`) carries no version segment.

## Controller catalog

| Controller | Route prefix | Base | Endpoints | Documentation |
| --- | --- | --- | --- | --- |
| `ConvertController` | `v1` | `ApiController` | 2 | [Details](endpoints/convert-controller.md) |
| `ExtractController` | `v1` | `ApiController` | 1 | [Details](endpoints/extract-controller.md) |
| `MergeController` | `v1` | `ApiController` | 1 | [Details](endpoints/merge-controller.md) |
| `LegacyController` | `v1/legacy` | `ApiController` | 1 | [Details](endpoints/legacy-controller.md) |
| `InfoController` | `v1/info` | `ApiController` | 7 | [Details](endpoints/info-controller.md) |
| `ApiInfoController` | — | `ApiController` | 1 | [Details](endpoints/api-info-controller.md) |

## Endpoint catalog

Exactly the required eight columns, in order. The **Auth** cell links to the service-wide authorization finding; the **Rules** cells link to `business-rules.md`.

| Endpoint | Method | Route | Purpose | Request | Response | Auth | Rules |
| --- | --- | --- | --- | --- | --- | --- | --- |
| [`Convert (request body)`](endpoints/convert-controller.md#post-v1%2Fconvert) | `POST` | `v1/convert` | Converts the document described by a `ConvertRequest` body to PDF or PDF/A, optionally tracking the request | `PdfAPI.Core.ConvertRequest` | `PdfAPI.Core.PdfResult` | [None in code](authentication-authorization.md#authorization-enforcement) | [BR-PDFAPI-017](business-rules.md#br-pdfapi-017-processing-failures-return-200-with-a-pdfresult) |
| [`Convert (raw bytes)`](endpoints/convert-controller.md#post-v1%2Fconvert%2F%7Bfileextension%7D) | `POST` | `v1/convert/{fileExtension}` | Converts a raw document byte array to PDF or PDF/A using route and query parameters instead of a request wrapper | `byte[]` (raw body) | `PdfAPI.Core.PdfResult` | [None in code](authentication-authorization.md#authorization-enforcement) | [BR-PDFAPI-017](business-rules.md#br-pdfapi-017-processing-failures-return-200-with-a-pdfresult) |
| [`ExtractPages`](endpoints/extract-controller.md#post-v1%2Fextract) | `POST` | `v1/extract` | Extracts one or more page ranges from a source PDF into a new output document | `PdfAPI.Core.ExtractPagesRequest` | `PdfAPI.Core.PdfResult` | [None in code](authentication-authorization.md#authorization-enforcement) | [BR-PDFAPI-004](business-rules.md#br-pdfapi-004-extraction-requires-pdf-validation), [BR-PDFAPI-018](business-rules.md#br-pdfapi-018-page-range-clamping-and-reversal) |
| [`Merge`](endpoints/merge-controller.md#post-v1%2Fmerge) | `POST` | `v1/merge` | Converts non-PDF inputs to PDF and merges all inputs into a single PDF output | `PdfAPI.Core.MergeRequest` | `PdfAPI.Core.PdfResult` | [None in code](authentication-authorization.md#authorization-enforcement) | [BR-PDFAPI-001](business-rules.md#br-pdfapi-001-null-merge-request-bypasses-the-error-envelope), [BR-PDFAPI-006](business-rules.md#br-pdfapi-006-merge-aborts-entirely-on-pre-conversion-failure), [BR-PDFAPI-007](business-rules.md#br-pdfapi-007-pdf-a-output-silently-downgraded) |
| [`Download`](endpoints/legacy-controller.md#get-v1%2Flegacy%2Fdownload%2F%7Btrackingid%7D) | `GET` | `v1/legacy/download/{trackingId}` | Downloads the output document for a previously tracked request, only when it succeeded | — | `PdfAPI.Core.PdfResult` | [None in code](authentication-authorization.md#authorization-enforcement) | [BR-PDFAPI-013](business-rules.md#br-pdfapi-013-download-requires-succeeded-status-and-output-path) |
| [`CheckPdfTrackingStatus`](endpoints/info-controller.md#get-v1%2Finfo%2Ftrack%2F%7Btrackingid%7D) | `GET` | `v1/info/track/{trackingId}` | Polls a tracking record's status, optionally sleeping and retrying while processing | — | `PdfAPI.Core.PdfTrackingInfo` | [None in code](authentication-authorization.md#authorization-enforcement) | [BR-PDFAPI-014](business-rules.md#br-pdfapi-014-status-check-polling-loop) |
| [`GetPageCount`](endpoints/info-controller.md#post-v1%2Finfo%2Fpages%2Fcount) | `POST` | `v1/info/pages/count` | Returns the page count of a submitted PDF | `byte[]` (raw body) | `int` | [None in code](authentication-authorization.md#authorization-enforcement) | [BR-PDFAPI-005](business-rules.md#br-pdfapi-005-pdf-validity-by-file-signature) |
| [`HasFormFields`](endpoints/info-controller.md#post-v1%2Finfo%2Ffields%2Fexist) | `POST` | `v1/info/fields/exist` | Reports whether a submitted PDF contains form fields | `byte[]` (raw body) | `bool` | [None in code](authentication-authorization.md#authorization-enforcement) | [BR-PDFAPI-021](business-rules.md#br-pdfapi-021-form-field-inspection-client-selection) |
| [`FlattenFormFields`](endpoints/info-controller.md#post-v1%2Finfo%2Ffields%2Fflatten) | `POST` | `v1/info/fields/flatten` | Flattens the form fields in a submitted PDF and returns the flattened bytes | `byte[]` (raw body) | `byte[]` | [None in code](authentication-authorization.md#authorization-enforcement) | [BR-PDFAPI-021](business-rules.md#br-pdfapi-021-form-field-inspection-client-selection) |
| [`IsPdf`](endpoints/info-controller.md#post-v1%2Finfo%2Fvalidate) | `POST` | `v1/info/validate` | Reports whether the submitted bytes are a valid PDF | `byte[]` (raw body) | `bool` | [None in code](authentication-authorization.md#authorization-enforcement) | [BR-PDFAPI-005](business-rules.md#br-pdfapi-005-pdf-validity-by-file-signature) |
| [`IsPdfa`](endpoints/info-controller.md#post-v1%2Finfo%2Fvalidate%2Fpdfa) | `POST` | `v1/info/validate/pdfa` | Reports whether a submitted PDF conforms to PDF/A | `byte[]` (raw body) | `bool` | [None in code](authentication-authorization.md#authorization-enforcement) | — |
| [`Version`](endpoints/info-controller.md#post-v1%2Finfo%2Fversion) | `POST` | `v1/info/version` | Returns the PDF version header found in a submitted document | `byte[]` (raw body) | `string` | [None in code](authentication-authorization.md#authorization-enforcement) | [BR-PDFAPI-005](business-rules.md#br-pdfapi-005-pdf-validity-by-file-signature) |
| [`GetBuildVersionData`](endpoints/api-info-controller.md#get-buildversion) | `GET` | `buildVersion` | Returns build/version metadata for the deployed service | — | `IEnumerable<KeyValuePair<string,string>>` | [None in code](authentication-authorization.md#authorization-enforcement) | — |

Every route above is fully resolved: the `v1`, `v1/info`, and `v1/legacy` prefixes shown are each controller's `[RoutePrefix]` composed with its action's `[Route]` fragment.
`ApiInfoController` carries no `[RoutePrefix]`, so its route (`buildVersion`) is documented with no version segment, per source. Controller, action, and error-code detail for each endpoint moved to its controller detail page under `endpoints/`.

## Error response shape

Two distinct facts about errors are documented across this API set and must not be conflated:

- **Known, framework/action-level error detail.** For the eight endpoints with no `try`/`catch`
  (`InfoController`'s seven actions, `ApiInfoController`'s one action), an uncaught exception is returned by the ASP.NET Web API framework with full exception detail, because `IncludeErrorDetailPolicy.Always` is set. For endpoints with a `try`/`catch` (`ConvertController`, `ExtractController`, `MergeController`, `LegacyController`), the action itself catches the exception and returns `200 OK` with a failed `PdfResult` body instead of an HTTP error. This is the detail recorded in the `Errors` tables on each endpoint's detail page under `endpoints/`.
- **Unknown outer envelope.** Every response above — success or error — additionally passes
  through the globally registered `ApiResponseHandler` message handler (`config.MessageHandlers.Add(new ApiResponseHandler());`, `PdfAPI\App_Start\WebApiConfig.cs`), which wraps or post-processes the HTTP response for the whole service. `ApiResponseHandler` is supplied by the `SAIF.Web.API` NuGet package; its exact wrapping/envelope shape is implemented inside that package and **is not visible in this repository**. The endpoint and operation pages therefore describe only the pre-envelope detail — the final wire-level response body shape is unknown until resolved from the `SAIF.Web.API` package's own documentation.

## Request flow diagram

The following diagram visualizes how a request reaches a handling action.

```mermaid
flowchart TD
    REQ["Client request"] --> ROUTE{"Attribute route match"}
    ROUTE -->|Match| A["Controller action"]
    ROUTE -->|No match| NF["404 Not Found"]
    A --> AUTH{"Authorization"}
    AUTH -->|None in code| OP["Service / business layer"]
    OP --> OK["200 OK"]
    OP --> ERR["500 Internal Server Error<br>(framework, uncaught exception)"]
```

## Endpoints by operation

| Endpoint | Operation |
| --- | --- |
| [`POST v1/convert`](endpoints/convert-controller.md#post-v1%2Fconvert) | [OP-CONVERT-REQUEST](operations/op-convert-request.md) |
| [`POST v1/convert/{fileExtension}`](endpoints/convert-controller.md#post-v1%2Fconvert%2F%7Bfileextension%7D) | [OP-CONVERT-FILE](operations/op-convert-file.md) |
| [`POST v1/extract`](endpoints/extract-controller.md#post-v1%2Fextract) | [OP-EXTRACT-PAGES](operations/op-extract-pages.md) |
| [`POST v1/merge`](endpoints/merge-controller.md#post-v1%2Fmerge) | [OP-MERGE-DOCUMENTS](operations/op-merge-documents.md) |
| [`GET v1/legacy/download/{trackingId}`](endpoints/legacy-controller.md#get-v1%2Flegacy%2Fdownload%2F%7Btrackingid%7D) | [OP-DOWNLOAD-BY-TRACKING-ID](operations/op-download-by-tracking-id.md) |
| [`GET v1/info/track/{trackingId}`](endpoints/info-controller.md#get-v1%2Finfo%2Ftrack%2F%7Btrackingid%7D) | [OP-CHECK-TRACKING-STATUS](operations/op-check-tracking-status.md) |
| [`POST v1/info/pages/count`](endpoints/info-controller.md#post-v1%2Finfo%2Fpages%2Fcount) | [OP-GET-PAGE-COUNT](operations/op-get-page-count.md) |
| [`POST v1/info/fields/exist`](endpoints/info-controller.md#post-v1%2Finfo%2Ffields%2Fexist) | [OP-HAS-FORM-FIELDS](operations/op-has-form-fields.md) |
| [`POST v1/info/fields/flatten`](endpoints/info-controller.md#post-v1%2Finfo%2Ffields%2Fflatten) | [OP-FLATTEN-FORM-FIELDS](operations/op-flatten-form-fields.md) |
| [`POST v1/info/validate`](endpoints/info-controller.md#post-v1%2Finfo%2Fvalidate) | [OP-IS-PDF](operations/op-is-pdf.md) |
| [`POST v1/info/validate/pdfa`](endpoints/info-controller.md#post-v1%2Finfo%2Fvalidate%2Fpdfa) | [OP-VALIDATE-PDFA](operations/op-validate-pdfa.md) |
| [`POST v1/info/version`](endpoints/info-controller.md#post-v1%2Finfo%2Fversion) | [OP-GET-PDF-VERSION](operations/op-get-pdf-version.md) |
| [`GET buildVersion`](endpoints/api-info-controller.md#get-buildversion) | [OP-GET-BUILD-VERSION](operations/op-get-build-version.md) |

## Related documentation
- [API index](index.md)
- [Overview](overview.md)
- [Architecture](architecture.md)
- [Authentication and authorization](authentication-authorization.md)
- [Dependencies](dependencies.md)
- [Configuration](configuration.md)
- [Operations and processes](operations-processes.md)
- [Business rules](business-rules.md)
- [Data model](data-model.md)
- [Operational runbook](operational-runbook.md)
- [Tech debt](tech-debt.md)

> **Note:** Statements marked with `*` were inferred from code structure, naming conventions, or
> contextual evidence where direct confirmation was not available in source artifacts. Statements
> marked with `**` could not be confirmed; treat as unknown until verified.

## Sources
- PdfAPI\App_Start\WebApiConfig.cs
- PdfAPI\Controllers\v1\ConvertController.cs
- PdfAPI\Controllers\v1\ExtractController.cs
- PdfAPI\Controllers\v1\MergeController.cs
- PdfAPI\Controllers\v1\LegacyController.cs
- PdfAPI\Controllers\v1\InfoController.cs
- PdfAPI\Controllers\v1\ApiInfoController.cs
